package cn.pconline.autoclub.task.data;

import cn.pconline.autoclub.task.DBUtils;
import cn.pconline.autoclub.task.FileUtils;
import cn.pconline.autoclub.task.util.IdGeneratorByTable;
import cn.pconline.autoclub.task.util.LogUtils;
import cn.pconline.autoclub.task.util.PcHttpUtils;
import cn.pconline.r.client.SimpleHttpTemplate;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SyncTopicImage {

    private static final Logger log = LoggerFactory.getLogger(SyncTopicImage.class);
    private static final int PAGE_SIZE = 1000;
    private static IdGeneratorByTable idGenerator = new IdGeneratorByTable();
    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
    static List<String> columns = null;

    static {
        try {
            columns = DBUtils.getColumns("ac_dyna_image");
        } catch (SQLException e) {
            log.error("get reply table columns error.", e);
        }
    }

    public static void main(String[] args) {
        LogUtils.initLog();
        if (args != null && args.length > 0 && "test".equalsIgnoreCase(args[0])) {
            log.info("test sync run ...");
            return;
        }

        try {
            int count = 0;
            if (args != null && args.length > 0) {
                String table = args[0];
                List<String> tables = DBUtils.getTables("ac_dyna_info", 4);
                if (tables.contains(table)) {
                    log.info("start sync table: {}", table);
                    count = syncTopicImg(table);
                } else {
                    log.info("table[{}] name is not exists", table);
                }
            } else {
                count = syncTopicImg();
            }
            log.info("total sync {} images.", count);
        } catch (SQLException e) {
            log.error("sync dyna images error.", e);
        }
    }

    private static int syncTopicImg() throws SQLException {
        List<String> tables = DBUtils.getTables("ac_dyna_info", 4);
        int syncCount = 0;
        for (String table : tables) {
            syncCount = syncTopicImg(table);
        }
        return syncCount;
    }

    private static int syncTopicImg(String table)
            throws SQLException {
        log.info("sync table[{}] start", table);
        int syncCount = 0;
        int pageCount = getPageCount(table);
        int page = 1;
        while (page <= pageCount) {
            log.debug("sync page info {}/{}", page, pageCount);
            List<Map<String, Object>> dynas = getDynaInfos(table, page);
            log.debug("page[{}] dynas:\n{}", page, dynas);
            for (Map<String, Object> dynaInfo : dynas) {
                long topicId = (Long) dynaInfo.get("topic_id");
                long dynaId = (Long) dynaInfo.get("dyna_info_id");
                List<Map<String, Object>> topicImgs = getTopicImages(topicId);
                if (topicImgs == null || topicImgs.size() <= 0) {
                    continue;
                }
                log.debug("topic[{}] images:\n{}", topicId, topicImgs);
                List<Map<String, Object>> dynaImgs = topicImg2DynaImg(dynaId, topicImgs);

                addTopicImages(dynaInfo, dynaImgs);
                syncCount += topicImgs.size();
            }
            page++;
        }
        log.info("sync table[{}] finish", table);
        return syncCount;
    }

    private static List<Map<String, Object>> topicImg2DynaImg(long dynaId, List<Map<String, Object>> topicImgs) {
        List<Map<String, Object>> dynaReplies = new ArrayList<Map<String, Object>>();
        for (Map<String, Object> topicImg : topicImgs) {
            dynaReplies.add(topicImg2DynaImg(dynaId, topicImg));
        }
        return dynaReplies;
    }

    private static int[] addTopicImages(Map<String, Object> dynaInfo, List<Map<String, Object>> dynaImgs) throws SQLException {
        long dynaId = (Long) dynaInfo.get("dyna_info_id");
        Date createDate = (Date) dynaInfo.get("create_date");
        //long clubId = (Long)dynaInfo.get("club_id");

        StringBuilder colBuilder = new StringBuilder();
        StringBuilder paramBuilder = new StringBuilder();
        if (columns == null) {
            columns = DBUtils.getColumns("ac_dyna_image");
        }
        for (String col : columns) {
            colBuilder.append(",").append(col);
            paramBuilder.append(",?");
        }
        String table = "ac_dyna_image_" + (dynaId % 10);
        StringBuilder sqlBuilder = new StringBuilder();
        sqlBuilder.append("insert into ").append(table).append(" (");
        sqlBuilder.append(colBuilder.substring(1));
        sqlBuilder.append(") values (");
        sqlBuilder.append(paramBuilder.substring(1));
        sqlBuilder.append(")");

        String dynaTable = "ac_dyna_info_" + sdf.format(createDate);
        String updateSql = "update " + dynaTable + " set is_pic = 1 where dyna_info_id = " + dynaId;
        //String updateIdxSql = "update ac_club_dyna_" + (clubId%10) + " set post_count = "+replyCnt
        //    + " where dyna_info_id = " + dynaId + " and club_id = " + clubId;

        Connection conn = null;
        PreparedStatement ps = null;
        Statement stmt = null;
        boolean isAutoCommit = false;
        try {
            conn = DBUtils.getConnection();
            isAutoCommit = conn.getAutoCommit();
            conn.setAutoCommit(false);
            log.debug("insert sql: {}", sqlBuilder);
            ps = conn.prepareStatement(sqlBuilder.toString());
            log.debug("columns: {}", columns);
            for (Map<String, Object> image : dynaImgs) {
                int idx = 1;
                log.debug("image: {}", image);
                for (String col : columns) {
                    ps.setObject(idx++, image.get(col));
                }
                ps.addBatch();
            }
            int[] cnt = ps.executeBatch();
            log.info("add image : {}", Arrays.toString(cnt));
            stmt = conn.createStatement();
            log.info("update dyna info reply count: {}", updateSql);
            stmt.addBatch(updateSql);
            stmt.executeBatch();
            conn.commit();
            return cnt;
        } catch (SQLException ex) {
            conn.rollback();
            throw ex;
        } finally {
            if (conn != null) {
                conn.setAutoCommit(isAutoCommit);
            }
            DBUtils.releaseConn(conn, ps, null);
        }
    }

    private static Map<String, Object> topicImg2DynaImg(long dynaId, Map<String, Object> topicImg) {
        Map<String, Object> image = new HashMap<String, Object>();

        String tableName = "ac_dyna_image";

        image.put("image_id", idGenerator.generate(tableName, "image_id"));
        image.put("dyna_info_id", dynaId);
        image.put("url", topicImg.get("url"));
        image.put("width", topicImg.get("width"));
        image.put("height", topicImg.get("height"));
        image.put("seq", topicImg.get("seq"));
        return image;
    }

    private static List<Map<String, Object>> getTopicImages(long topicId) {
        SimpleHttpTemplate simpleHttpTemplate = PcHttpUtils.getSimpleHttpTemplate();
        String url = FileUtils.getConfig("autobbs.root") + "/plugins/autoclub/getImagesByTid.do?size=9&topicId=" + topicId;//4084163
        //url = "http://192.168.32.21/bbs7/plugins/autoclub/getImagesByTid.do?topicId="+topicId;
        String result = simpleHttpTemplate.get(url, "http://club.pcauto.com.cn");
        log.debug("get {}\nresult:\n{}", url, result);
        if (result != null) {
            ObjectMapper mapper = new ObjectMapper();
            try {
                @SuppressWarnings("unchecked")
                List<Map<String, Object>> imgList = mapper.readValue(result, List.class);
                if (imgList != null && imgList.size() > 0) {
                    return imgList;
                } else {
                    log.warn("not get[{}] images : {}", topicId, url);
                }
            } catch (JsonParseException e) {
                log.error("", e);
            } catch (JsonMappingException e) {
                log.error("", e);
            } catch (IOException e) {
                log.error("", e);
            }
        }
        return null;
    }

    private static int getPageCount(String table) throws SQLException {
        int total = getTotal(table);
        if (total <= 0) {
            return 0;
        }
        return (total - 1) / PAGE_SIZE + 1;
    }

    private static List<Map<String, Object>> getDynaInfos(String table, int pageNo) throws SQLException {
        String sql = "select dyna_info_id, topic_id, club_id, create_date from " + table + " where topic_id > 0 and type = 1 and dyna_info_id < 48117 "
                + " limit " + (pageNo - 1) * PAGE_SIZE + "," + PAGE_SIZE;
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet resultSet = null;
        List<Map<String, Object>> dynas = new ArrayList<Map<String, Object>>();
        try {
            conn = DBUtils.getConnection();
            ps = conn.prepareStatement(sql);
            resultSet = ps.executeQuery();
            if (resultSet != null) {
                while (resultSet.next()) {
                    Map<String, Object> row = new HashMap<String, Object>();
                    row.put("dyna_info_id", resultSet.getLong("dyna_info_id"));
                    row.put("club_id", resultSet.getLong("club_id"));
                    row.put("topic_id", resultSet.getLong("topic_id"));
                    row.put("create_date", resultSet.getDate("create_date"));
                    dynas.add(row);
                }
            }
        } catch (SQLException ex) {
            throw ex;
        } finally {
            DBUtils.releaseConn(conn, ps, resultSet);
        }
        return dynas;
    }

    private static int getTotal(String table) throws SQLException {
        String sql = "select count(1) from " + table + " where topic_id > 0 and type = 1 and dyna_info_id < 48117";
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet resultSet = null;
        log.debug("table total sql: {}", sql);
        try {
            conn = DBUtils.getConnection();
            ps = conn.prepareStatement(sql);
            resultSet = ps.executeQuery();
            if (resultSet != null && resultSet.next()) {
                return resultSet.getInt(1);
            }
        } catch (SQLException ex) {
            throw ex;
        } finally {
            DBUtils.releaseConn(conn, ps, resultSet);
        }
        return 0;
    }
}
